<html>
<head>	
	<LINK href="./css/common.css" rel="stylesheet" type="text/css">
	<LINK href="./css/tutorial.css" rel="stylesheet" type="text/css">
	
    <script type="text/javascript" src="Lib/Moshu.js"></script>
    <script type="text/javascript" src="Lib/Moshu.Canvas2D.js"></script>
	<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.min.js"></script>
	<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/jquery-ui.min.js"></script>
	<link href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.10/themes/ui-lightness/jquery-ui.css" rel="stylesheet" type="text/css" />
    <style type="text/css">
        #score{
            width:300px;
            font-size:16px;
            font-weight:bold;
        }
    </style>
</head>
<body>
	
	<div class="page">
		<div class="page-header ">
			<div class="title">
				<span>Moshu's Canvas Library</span>
			</div>		
			<div class="menu"></div>			
		</div>
		<div class="page-content" style="overflow-y:scroll;">
			<div style="width:80%;margin-left:10%;margin-top:2%;margin-bottom:2%;">
				<h1>Moshu's Canvas Library - Tetris demo</h1>
                <div>
                    <button value="- level" onclick="changeLevel(-1)">- level</button>
                    <span id="currentLevel"></span>
                    <button value="+ level" onclick="changeLevel(1)">+ level</button>
                    <button value="+ level" onclick="reset(1)">Reset</button>
                </div>
                <canvas id="c"  width="460" height="760" border="1" style="border:1px solid black; background-image:url(images/img.jpg);"></canvas>
                <div id="score">Score : 0</div>
			</div>
		</div>
	</div>
	<div class="page-footer">
	</div>

	<script type="text/javascript">
	    $(".menu").load("partials/menu.html");
	    $(".page-footer").load("partials/footer.html");
	    $(".resizable").resizable();
	</script>
	
	 <script type="text/javascript">
	     function Tetris(canvasId) {
	         this.canvasId = canvasId;
	         this.world = new Moshu.Canvas2D.World(this.canvasId);
	         this.world.supressTimer();
	         this.size = {
	             width: this.world.canvas.width,
	             height: this.world.canvas.height,
	         };
	         this.worldOffset = {
	             left: 50,
	             top: 50,
	             right: 50,
                 bottom:50
	         }
	         this.startPosition = {
	             x: 30 * 5 + this.worldOffset.left,
	             y: this.worldOffset.top,
	         }
	         this.squareSize = 30;
	         this.fallingShape = {
	             shapes: []                 
	         }
	         this.addEventListener = function (obj, evt, fnc) {
	             // W3C model
	             if (obj.addEventListener) {
	                 obj.addEventListener(evt, fnc, false);
	                 return true;
	             }
	                 // Microsoft model
	             else if (obj.attachEvent) {
	                 return obj.attachEvent('on' + evt, fnc);
	             }
	                 // Browser don't support W3C or MSFT model, go on with traditional
	             else {
	                 evt = 'on' + evt;
	                 if (typeof obj[evt] === 'function') {
	                     // Object already has a function on traditional
	                     // Let's wrap it with our own function inside another function
	                     fnc = (function (f1, f2) {
	                         return function () {
	                             f1.apply(this, arguments);
	                             f2.apply(this, arguments);
	                         }
	                     })(obj[evt], fnc);
	                 }
	                 obj[evt] = fnc;
	                 return true;
	             }
	             return false;
	         };
	         this.cancelEvent = function (event) {
	             if (window.event) {
	                 window.event.returnValue = false;
	             }
	             else if (event.preventDefault) {
	                 event.preventDefault();
	             }
	             else {
	                 event.returnValue = false;
	             }
	         };
	         this._score = 0;
	         this.score = function (val) {
	             
	             if (typeof (val) == "number") {
	                 this._score += val;
	                 if (val != 0) {
	                     debugger;
	                     if (scoreChanged)
	                         scoreChanged(this._score);
	                 }
	             }
	             return this._score;
	         }
	         this.init = function () {
	             this._score = 0;

	             // add walls
	             var wallTop = new Moshu.Canvas2D.Rectangle(0, 0, this.size.width, this.worldOffset.top);
	             var wallBottom = new Moshu.Canvas2D.Rectangle(0, this.size.height - this.worldOffset.bottom, this.size.width, this.size.height);

	             var wallLeft = new Moshu.Canvas2D.Rectangle(0, 0, this.worldOffset.left, this.size.height);
	             var wallRight = new Moshu.Canvas2D.Rectangle(this.size.width - this.worldOffset.right, 0, this.size.width, this.size.height);

	             wallTop.isFix

	             this.world.createShapeFromPolygon(wallTop);
	             this.world.createShapeFromPolygon(wallBottom);

	             this.world.createShapeFromPolygon(wallLeft);
	             this.world.createShapeFromPolygon(wallRight);

	             wallTop.painter.fill.enabled = true;
	             wallTop.painter.fill.color = "#0A1F33";
	             wallTop.painter.stroke.color = "#0A1F33";
	             wallRight.fixed = true;

	             wallBottom.painter.fill.enabled = true;
	             wallBottom.painter.fill.color = "#0A1F33";
	             wallBottom.painter.stroke.color = "#0A1F33";
	             wallBottom.fixed = true;

	             wallLeft.painter.fill.enabled = true;
	             wallLeft.painter.fill.color = "#0A1F33";
	             wallLeft.painter.stroke.color = "#0A1F33";
	             wallLeft.fixed = true;

	             wallRight.painter.fill.enabled = true;
	             wallRight.painter.fill.color = "#0A1F33";
	             wallRight.painter.stroke.color = "#0A1F33";
	             wallRight.fixed = true;

	             this.wallLeft = wallLeft;
	             this.wallRight = wallRight;
	             this.wallTop = wallTop;
	             this.wallBottom = wallBottom;
	             
	             this.world.refresh();

	             

	             var self = this;
	             this.addEventListener(window, "keydown", function (e) {
	                 var evt = (e) ? e : (window.event) ? window.event : null;
	                 
	                 if (evt) {
	                     self.slowDownDescent();
	                     var key = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : ((evt.which) ? evt.which : 0));	                     
	                     if (key == 37) {
	                         // left
	                         self.moveShapeLeft.call(self);
	                         self.cancelEvent(evt);
	                     }
	                     if (key == 38) {
	                         // up	 

	                         self.rotateShape();
	                         self.cancelEvent(evt);
	                     }
	                     if (key == 39) {
	                         // left
	                         self.moveShapeRight.call(self);
	                         self.cancelEvent(evt);
	                     }
	                     if (key == 40) {
	                         // down
	                         self.speedUpDescent();
	                         self.cancelEvent(evt);
	                     }

	                 }
	                 
	             });

	             this.addEventListener(window, "keyup", function (e) {	                 
	                 var evt = (e) ? e : (window.event) ? window.event : null;	                 
	                 if (evt) {
	                     var key = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : ((evt.which) ? evt.which : 0));
	                     if (key == 40) {
	                         // down
	                         self.slowDownDescent();
	                         self.cancelEvent(evt);
	                     }
	                 }	                 
	             });
	         }

	         this.moveDownTimer = null;
	         this.currentSpeed = 1;
             

	         this.randomFromTo = function(from, to) {
	             return Math.floor(Math.random() * (to - from + 1) + from);
	         }

	         this.reset = function () {
	             clearTimeout(this.moveDownTimer);
	             this.world.clear();
	             this.init();
	             this.createShape();
	         }
	        


	         
	         this.shapeTypesCount = 5;
             this.blockImage = "./Images/block.png",
	         this.getPossibleShape = function (idx) {
	             // create possible shapes
	             var offX = this.startPosition.x;
	             var offY = this.startPosition.y;
	             var blockImage = this.blockImage;
	             switch (idx) {
	                 case 0:
	                     return {
	                         name: "3 rectangles",
	                         shapes: [
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize * 2, this.squareSize, this.squareSize),
	                         ]
	                     };
	                 case 1:
	                     return {
	                         name: "4 rectangles - in a square",
	                         shapes: [
                                 new Moshu.Canvas2D.CanvasImage(blockImage,offX, offY, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),
	                         ]
	                     };
                    case 2:
	                     return {
	                         name: "4 rectangles - in L shape",
	                         shapes: [
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY, this.squareSize, this.squareSize),
	                         ]
	                     };
	                 case 3:
	                     return {
	                         name: "4 rectangles - in L shape reversed",
	                         shapes: [
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize + this.squareSize, offY, this.squareSize, this.squareSize),
	                         ]
	                     };
	                 case 4:
	                     return {
	                         name: "4 rectangles - in decalated",
	                         shapes: [
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize + this.squareSize, offY, this.squareSize, this.squareSize),

                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),                                 
	                         ],                             
	                     };
	                 case 5:
	                     return {
	                         name: "4 rectangles - in decalated reversed",
	                         shapes: [
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX - this.squareSize, offY, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX , offY, this.squareSize, this.squareSize),

                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX, offY + this.squareSize, this.squareSize, this.squareSize),
                                 new Moshu.Canvas2D.CanvasImage(blockImage, offX + this.squareSize, offY + this.squareSize, this.squareSize, this.squareSize),
	                         ]
	                     };
	             }	             
	         }

	         this.createShape = function () {
	             var offX = this.startPosition.x;
	             var offY = this.startPosition.y;
	             var rand = this.randomFromTo(0, this.shapeTypesCount);	             
	             this.fallingShape = this.getPossibleShape(rand);
	             // add shapes to world	             
	             
	             for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                 this.fallingShape.shapes[i].isSettled = false;	                 
	                 this.world.createShapeFromImage(this.fallingShape.shapes[i]);
	             }
	             this.world.refresh();

	             var self = this;
	             this.speed = this.currentSpeed;
	             this.moveDownTimer = setTimeout(function () {
	                 self.moveShapeDown.call(self);
	             }, 1000/this.speed);
	         }

	         this.rotateShape = function () {
	             if (this.fallingShape) {
	                 this.world.freeze();
	                 //get top-left corner
	                 var minVertice = null;
	                 var minx = this.size.width;
	                 for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                     var shape = this.fallingShape.shapes[i];
	                     var vertices = shape.getVertices();	                     
	                     for (var j = 0; j < vertices.length  ; j++) {
	                         if (vertices[j].x() < minx) {
	                             minx = vertices[j].x();
	                             minVertice = vertices[j];
	                         }	                         
	                     }
	                 }
	                 var rotationVertice = new Moshu.Canvas2D.Vector(minVertice.x(), minVertice.y());
	                 for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                     var shape = this.fallingShape.shapes[i];
	                     //debugger;
	                     shape.save();
	                     shape.rotate(Math.PI / 2, rotationVertice);
	                 }
	                 // check if after rotation we intersect left wall
	                 //get left-most corner
	                 var minVertice = null;
	                 var maxVertice = null;
	                 var minx = this.size.width;
	                 var maxx = 0;
	                 minVertice = null;
	                 maxVertice = null;
	                 maxy = 0;
	                 for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                     var shape = this.fallingShape.shapes[i];
	                     var vertices = shape.getVertices();
	                     
	                     for (var j = 0; j < vertices.length  ; j++) {
	                         if (vertices[j].x() < minx) {
	                             minx = vertices[j].x();
	                             minVertice = vertices[j];
	                         }
	                         if (vertices[j].x() > maxx) {
	                             maxx = vertices[j].x();
	                             maxVertice = vertices[j];
	                         }
	                         if (vertices[j].y() > maxy) {
	                             maxy = vertices[j].y();	                             
	                         }
	                     }
	                 }
	                 
	                 if (minVertice.x() < this.worldOffset.left) {
	                     // hit left wall
	                     //debugger;
	                     var dx = this.worldOffset.left - minVertice.x();
	                     this.moveShape(new Moshu.Canvas2D.Vector(dx, 0));
	                 }
	                 if (maxVertice.x() > this.size.width - this.worldOffset.right) {
	                     // hit right wall
	                     //debugger;
	                     var dx = maxVertice.x() - this.size.width - this.worldOffset.right;
	                     this.moveShape(new Moshu.Canvas2D.Vector(-dx,0));
	                 }
	                 if (maxy > this.size.height - this.worldOffset.bottom) {
	                     // hit bottom wall
	                     // revert the rotation
	                     for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                         var shape = this.fallingShape.shapes[i];	                         
	                         shape.restore();	                         
	                     }
	                 }
	                 // check collisions with all other shapes in the scene	
	                 var c = null;
	                 for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                    var shape = this.fallingShape.shapes[i];	   
	                    for (var j = 0; j < this.world.shapes.length; j++) {
	                        var s = this.world.shapes[j];
	                        if (s && s.isSettled) {
	                            c = shape.getCollision(s);
	                            if (c) {
	                                // revert the rotation
	                                debugger;
	                                for (var k = 0; k < this.fallingShape.shapes.length;k++) {
	                                    var shape = this.fallingShape.shapes[k];
	                                    shape.restore();	                                    
	                                }
	                                break;
	                            }
	                        }
	                    }
	                    if (c) break;
                     }
	                 this.world.unfreeze();
	                 this.world.refresh();
	             }
	         }

	         this.speedUpDescent = function () {
	             
	             if (this.speed != 20) {
	                 this.speed = 20;
	                 clearTimeout(this.moveDownTimer);
	                 this.moveShapeDown();
	             }
	             console.log(this.speed);
	         }

	         this.slowDownDescent = function () {
	             this.speed = this.currentSpeed;
	             console.log(this.speed);
	         }

	         this.checkRowsComplete = function (score) {
	             if (!score) score = 0;
	             var minX = this.worldOffset.left + this.squareSize / 2;	             
	             var maxX = this.size.width - this.worldOffset.right;

	             var minY = this.worldOffset.top;	             
	             var maxY = this.size.height - this.worldOffset.bottom - this.squareSize / 2;

	             var indent = this.squareSize;

	             //debugger;
	             for (var y = maxY; y > minY; y -= indent) {
	                 // check this row
	                 needsDeletion = true;
	                 var foundShapes = [];
	                 for (var x = minX; x < maxX; x += indent) {
	                     var found = false;	                     
	                     for (var j = 0; j < this.world.shapes.length; j++) {
	                         var shape = this.world.shapes[j];
	                         if (shape.isSettled) {
	                             var b = shape.getBoundary();
	                             if (b[0] < x && b[2] > x && b[1] < y && b[3] > y) {
	                                 // shape contains point
	                                 found = true;
	                                 foundShapes.push(shape);
	                                 break;
	                             }
	                         }
	                     }
	                     if (!found) {
	                         needsDeletion = false;
	                         break;
	                     }
	                 }
	                 if (needsDeletion) {
	                     // delete the row
	                     for (var i = 0; i < foundShapes.length; i++) {                             
	                         this.world.remove(foundShapes[i]);
	                     }
	                     // move all shapes above 1 row
	                     for (var j = 0; j < this.world.shapes.length; j++) {
	                         var shape = this.world.shapes[j];
	                         if (shape.isSettled) {	                             
	                             var v = shape._vertices[0];
	                             if (v.y() < y) {
	                                 var distance = new Moshu.Canvas2D.Vector(0, this.squareSize);
	                                 shape.move(distance);
	                             }
	                         }
	                     }	                     
	                     score = this.checkRowsComplete(score*2+10*this.currentSpeed);
	                     break;
	                 }
	             }
	             return score;
	         }

	         this.moveShapeDown = function () {	             
	             var distance = new Moshu.Canvas2D.Vector(0, this.squareSize);
	             this.moveShape(distance);	             

	             if (this.fallingShape) {
                     // still moving
	                 var self = this;
	                 this.moveDownTimer = setTimeout(function () {
	                     self.moveShapeDown.call(self);
	                 }, 1000 / this.speed);
	             }
	             else {
                     // create new shape
	                 this.createShape();
	             }
	         }
	         this.moveShapeLeft = function () {
	             var distance = new Moshu.Canvas2D.Vector(-this.squareSize, 0);
	             this.moveShape(distance);	             
	         }
	         this.moveShapeRight = function () {
	             var distance = new Moshu.Canvas2D.Vector(this.squareSize, 0);
	             //debugger;
	             this.moveShape(distance);
	         }
	         this.moveShape = function (distance) {
	             if (!this.fallingShape)return;
	             //debugger;
	             //distance.x(distance.x() / 2);
	             //distance.y(distance.y() / 2);
	             for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                 var shape = this.fallingShape.shapes[i];

	                 shape.move(distance);
	             }
	             var revert = false;
	             var destroy = false;
	             for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                 var shape = this.fallingShape.shapes[i];
	                 c = shape.getCollision(this.wallLeft);
	                 if (c) {
	                     revert = true;
	                     break;
	                 }
	                 c = shape.getCollision(this.wallRight);
	                 if (c) {
	                     revert = true;
	                     break;
	                 }
	                 c = shape.getCollision(this.wallBottom);
	                 if (c) {
	                     destroy = true;
	                     revert = true;
	                     break;
	                 }
	                 // get collisions with all other shapes in the scene	                 
	                 for (var j = 0; j < this.world.shapes.length; j++) {
	                     var s = this.world.shapes[j];
	                     if (s && s.isSettled) {	                         
	                         c = shape.getCollision(s);
	                         if (c) {	                             
	                             revert = true;	                             
	                             // check if moving down
	                             if(distance.y()>0)
	                             {
	                                 destroy = true;
	                             }
	                             break;
	                         }
	                     }
	                 }
	             }	             
	             if (revert) {
	                 for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                     var shape = this.fallingShape.shapes[i];
	                     revertDistance = new Moshu.Canvas2D.Vector(-distance.x(), -distance.y());
	                     shape.move(revertDistance);
	                 }
	                 if (destroy) {
	                     for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                         this.fallingShape.shapes[i].isSettled = true;
	                     }
	                     this.fallingShape = null;

                         // we might want to check if we want to remove the completed rows here?
	                     var score = this.checkRowsComplete();
	                     this.score(score);
	                 }
	             }
	             else {
	                 //for (var i = 0; i < this.fallingShape.shapes.length; i++) {
	                 //    var shape = this.fallingShape.shapes[i];	                     
	                 //    shape.move(distance);
	                 //}
	             }
	             this.world.refresh();
	         }

	     }
	     var tetris = new Tetris("c");
	     tetris.init();
	     tetris.createShape();

	     function scoreChanged(score) {
	         $("#score").html("Score: " + score);
	     }
	     function changeLevel(lvl) {
	         if (tetris.currentSpeed + lvl > 0) {
	             tetris.currentSpeed += lvl;
	             tetris.speed = tetris.currentSpeed;
	         }
	         $("#currentLevel").html("Level " + tetris.currentSpeed);
	     }
	     changeLevel(0);

	     function reset() {
	         tetris.reset();
	     }
    </script>    
</body>
</html>